# -*- coding: utf-8 -*-
# created on 2016/8/15


from mathsolver.functions.base import *
from sympy import LC, solve, collect
from mathsolver.functions.sympy_utils import safe_degree
from sympy.abc import x, y
from mathsolver.functions.fangcheng.budengshi import FangChenBuDengShi001
from mathsolver.functions.root.jiefangchenzu import JieFangChenZu
from mathsolver.functions.fangcheng.fangcheng import DaiRuFangChenZu


# 判断方程是否是二元一次方程
class ErYuanYiCiDistinguish(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        eq = (f1 - f2).expand().simplify()
        answer = True
        symbols = eq.free_symbols

        if len(symbols) != 2:
            answer = False
            self.steps.append(["", "该方程不是二元一次方程"])
        else:
            for a1, a2 in itertools.combinations(symbols, 2):
                if eq.has(a1 * a2):
                    answer = False
            for symbol in symbols:
                if safe_degree(eq, symbol) != 1:
                    answer = False
                    break
        if answer:
            self.steps.append(["", "该方程是二元一次方程"])
        else:
            self.steps.append(["", "该方程不是二元一次方程"])

        self.label.add("二元一次方程的判断")
        self.output.append(BaseVariable(answer))
        return self


# 根据二元一次方程的定义求参
class ErYuanYiCiDingYi(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        symbol_x = x
        symbol_y = y
        symbol = [symbol_x, symbol_y]
        if (f1 - f2).has(symbol_x * symbol_y):
            f3 = (f1 - f2).simplify()
        else:
            f3 = collect((f1 - f2).simplify(), symbol)
        parts = []
        ineqs = []
        for args in f3.args:
            part = args
            part_symbol = list(part.free_symbols.difference(symbol))
            if part_symbol:
                parts.append(part)
        for part in parts:
            if part.has(symbol_x * symbol_y):
                ineqs.append([part / (symbol_x * symbol_y), S.Zero])
            else:
                if part.is_Mul:
                    if part.args[1] == symbol_x or part.args[1] == symbol_y:
                        ineqs.append([part.args[0], "!=", S.Zero])
                    elif part.args[0] == symbol_x or part.args[0] == symbol_y:
                        ineqs.append([part.args[1], "!=", S.Zero])
                    elif part.args[0].is_Pow:
                        if not list(part.args[0].free_symbols.difference(symbol)):
                            ineqs.append([part.args[1], S.Zero])
                        else:
                            ineqs.append([part.args[0].args[1], 1])
                            if list(part.args[1].free_symbols.difference(symbol)):
                                ineqs.append([part.args[1], "!=", S.Zero])
                    elif part.args[1].is_Pow:
                        if not list(part.args[1].free_symbols.difference(symbol)):
                            ineqs.append([part.args[0], S.Zero])
                        else:
                            ineqs.append([part.args[1].args[1], 1])
                            if list(part.args[0].free_symbols.difference(symbol)):
                                ineqs.append([part.args[0], "!=", S.Zero])
                if part.is_Pow:
                    ineqs.append([part.args[1], 1])
        self.steps.append(["", "%s = %s 是二元一次方程" % (new_latex(f1), new_latex(f2))])
        if len(ineqs) > 1:
            self.steps.append(["所以", self.output_eqs(ineqs)])
            self.output.append(base_gen(ineqs))
        else:
            self.steps.append(["所以", self.output_eq(ineqs[0])])
            self.output.append(base_gen(ineqs[0]))
        self.label.add("根据二元一次方程的定义求参")
        return self


# 求二元一次方程的正整数解
class ErYuanYiCiZhengZhengShuJie(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        eq_original = [f1, "=", f2]
        f = (f1 - f2).simplify()
        symbol = list(f.free_symbols)
        assert len(symbol) == 2
        a1, h1 = f.as_independent(symbol[0])
        symbol0_coff = LC(h1)
        a2, h2 = f.as_independent(symbol[1])
        symbol1_coff = LC(h2)

        if symbol0_coff >= symbol1_coff:
            answer_set = solve(f, symbol[1])
            answer = answer_set[0]
            ineq = [answer, ">=", 1]
            stepsolver = FangChenBuDengShi001(verbose=True).solver(BaseIneq(ineq))
            jie = stepsolver.output[0].value[symbol[0]]
            ll, r, lopen, ropen = jie.args
            assert r.is_finite, "must be close interval"
            if ll <= 0:
                ll, lopen = S.Zero, True

            if ll.is_Integer:
                if lopen:
                    left = ll + 1
                else:
                    left = ll
            else:
                if ll > 0:
                    left = int(ll) + 1
                else:
                    left = int(ll)

            if r.is_Integer:
                if ropen:
                    right = r - 1
                else:
                    right = r
            else:
                if r > 0:
                    right = int(r)
                else:
                    right = int(r) - 1
            zhengzhengshujie = range(left, right + 1)
            eq = [symbol[1], "=", answer]
            self.steps.append(["依题意，得", self.output_eq(eq)])
            self.steps.append(["", "因为%s与%s是正整数，得" % (new_latex(symbol[0]), new_latex(symbol[1]))])
            ineq = [answer, ">=", 1]
            self.steps.append(["", self.output_eq(ineq)])
            self.steps.append(["解得", self.output_interval(symbol[0], jie)])
            self.steps.append(["所以", self.output_answer({symbol[0]: zhengzhengshujie})])
            x_jie = []
            y_jie = []
            for v in zhengzhengshujie:
                answer_y = answer.subs(symbol[0], v)
                if answer_y.is_integer:
                    self.steps.append(["", "当%s = %s 时，%s = %s" % (new_latex(symbol[0]), new_latex(v), new_latex(symbol[1]), new_latex(answer_y))])
                    y_jie.append(answer_y)
                    x_jie.append(v)
                else:
                    self.steps.append(["", "当%s = %s 时，%s = %s, 舍去" % (new_latex(symbol[0]), new_latex(v), new_latex(symbol[1]), new_latex(answer_y))])
            self.steps.append(["", "所以，方程%s的正整数解为: %s" % (self.output_eq(eq_original), self.output_jies({symbol[0]: x_jie, symbol[1]: y_jie}))])
            answer_final = {symbol[0]: x_jie, symbol[1]: y_jie}
        else:
            answer_set = solve(f, symbol[0])
            answer = answer_set[0]
            ineq = [answer, ">=", 1]
            stepsolver = FangChenBuDengShi001(verbose=True).solver(BaseIneq(ineq))
            jie = stepsolver.output[0].value[symbol[1]]
            ll, r, lopen, ropen = jie.args
            assert r.is_finite, "must be close interval"
            if ll <= 0:
                ll, lopen = S.Zero, True

            if ll.is_Integer:
                if lopen:
                    left = ll + 1
                else:
                    left = ll
            else:
                if ll > 0:
                    left = int(ll) + 1
                else:
                    left = int(ll)

            if r.is_Integer:
                if ropen:
                    right = r - 1
                else:
                    right = r
            else:
                if r > 0:
                    right = int(r)
                else:
                    right = int(r) - 1
            zhengzhengshujie = range(left, right + 1)
            eq = [symbol[0], "=", answer]
            self.steps.append(["依题意，得", self.output_eq(eq)])
            self.steps.append(["", "因为%s与%s是正整数，得" % (new_latex(symbol[0]), new_latex(symbol[1]))])
            ineq = [answer, ">=", 1]
            self.steps.append(["", self.output_eq(ineq)])
            self.steps.append(["解得", self.output_interval(symbol[1], jie)])
            self.steps.append(["所以", self.output_answer({symbol[1]: zhengzhengshujie})])
            x_jie = []
            y_jie = []
            for v in zhengzhengshujie:
                answer_x = answer.subs(symbol[1], v)
                if answer_x.is_integer:
                    self.steps.append(["", "当%s = %s 时，%s = %s" % (new_latex(symbol[1]), new_latex(v), new_latex(symbol[0]), new_latex(answer_x))])
                    x_jie.append(answer_x)
                    y_jie.append(v)
                else:
                    self.steps.append(["", "当%s = %s 时，%s = %s, 舍去" % (new_latex(symbol[1]), new_latex(v), new_latex(symbol[0]), new_latex(answer_x))])
            self.steps.append(["", "所以，方程%s的正整数解为: %s" % (self.output_eq(eq_original), self.output_jies({symbol[0]: x_jie, symbol[1]: y_jie}))])
            answer_final = {symbol[0]: x_jie, symbol[1]: y_jie}

        self.label.add("求二元一次方程的正整数解")
        self.output.append(BaseSymbolValue(answer_final))
        return self


# 求二元一次方程的正整数解组数
class ErYuanYiCiZhengZhengShuJieNumber(BaseFunction):
    def solver(self, *args):
        answer = args[0].value
        answer_number = len(answer[answer.keys()[0]])
        self.steps.append(["", "方程有%s组解" % new_latex(answer_number)])
        self.output.append(BaseNumber(answer_number))
        self.label.add("二元一次方程的正整数解组数")
        return self


# 用一个未知数表示另一个未知数
class ErYuanYiCi001(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        poly = args[1].sympify()
        f = (f1 - f2).simplify()
        a1, h1 = f.as_independent(poly)
        answer = solve(f, poly)
        self.steps.append(["移项,得", self.output_eq([h1, -a1])])
        # self.output.append(BaseEq([poly, answer[0]]))
        if LC(h1) != 1:
            self.steps.append(["系数化为1,得", self.output_eq([poly, answer[0]])])
        self.label.add("用一个未知数表示另一个未知数")
        return self


# 二元一次方程组同解问题
class ErYuanYiCiTongJie(BaseFunction):
    def solver(self, *args):
        eqs1 = args[0].sympify()
        eqs2 = args[1].sympify()
        f1 = (eqs1[0][0] - eqs1[0][1]).simplify()
        f2 = (eqs1[1][0] - eqs1[1][1]).simplify()
        f3 = (eqs2[0][0] - eqs2[0][1]).simplify()
        f4 = (eqs2[1][0] - eqs2[1][1]).simplify()
        f1_symbol = f1.free_symbols
        f2_symbol = f2.free_symbols
        f3_symbol = f3.free_symbols
        f4_symbol = f4.free_symbols
        eqs = []
        eqs_base = []
        if len(f1_symbol) <= 2:
            eqs.append([f1, "=", S.Zero])
            eqs_base.append(BaseEq([f1, S.Zero]))
        if len(f2_symbol) <= 2:
            eqs.append([f2, "=", S.Zero])
            eqs_base.append(BaseEq([f2, S.Zero]))
        if len(f3_symbol) <= 2:
            eqs.append([f3, "=", S.Zero])
            eqs_base.append(BaseEq([f3, S.Zero]))
        if len(f4_symbol) <= 2:
            eqs.append([f4, "=", S.Zero])
            eqs_base.append(BaseEq([f4, S.Zero]))
        assert len(eqs) == 2
        self.steps.append(["依题意，得", self.output_eqs(eqs)])
        stepsolver = JieFangChenZu(verbose=True).solver(BaseEqs([eqs_base[0].value, eqs_base[1].value]))
        jie = stepsolver.output[0].value
        a = jie.keys()[0]
        b = (jie[a])
        c = b.args[0]
        jie_final = {a[0]: c.args[0], a[1]: c.args[1]}
        eqs_final = []
        if len(f1_symbol) > 2:
            eqs_final.append([f1.subs(jie_final), "=", 0])
        if len(f2_symbol) > 2:
            eqs_final.append([f2.subs(jie_final), "=", 0])
        if len(f3_symbol) > 2:
            eqs_final.append([f3.subs(jie_final), "=", 0])
        if len(f4_symbol) > 2:
            eqs_final.append([f4.subs(jie_final), "=", 0])
        self.steps += stepsolver.steps
        self.label.add("二元一次方程组同解问题")
        self.steps.append(["代入，得", self.output_eqs(eqs_final)])
        self.output.append(BaseEqs([[eqs_final[0][0], S.Zero], [eqs_final[1][0], S.Zero]]))
        return self


# 根据二元一次方程解满足的条件，求参
class ErYuanYiCi002(BaseFunction):
    def solver(self, *args):
        eqs = args[0].sympify()
        eq = args[1].sympify()
        f1 = (eqs[0][0] - eqs[0][1]).simplify()
        f2 = (eqs[1][0] - eqs[1][1]).simplify()
        f3 = (eq[0] - eq[1]).simplify()
        f1_symbol = f1.free_symbols
        f2_symbol = f2.free_symbols
        f3_symbol = f3.free_symbols
        if type(args[1]) is BaseEq:
            eqs_original = []
            eqs_base_original = []
            if len(f1_symbol) == 2:
                eqs_original.append([f1, "=", S.Zero])
                eqs_base_original.append(BaseEq([f1, S.Zero]))
            if len(f2_symbol) == 2:
                eqs_original.append([f2, "=", S.Zero])
                eqs_base_original.append(BaseEq([f2, S.Zero]))
            if len(f3_symbol) == 2:
                eqs_original.append([f3, "=", S.Zero])
                eqs_base_original.append(BaseEq([f3, S.Zero]))
            if len(eqs_original) == 2:
                self.steps.append(["依题意，得", self.output_eqs(eqs_original)])
                stepsolver = JieFangChenZu(verbose=True).solver(BaseEqs([eqs_base_original[0].value,
                                                                         eqs_base_original[1].value]))
                self.append(stepsolver)
                jie = stepsolver.output[0].value
                a = jie.keys()[0]
                b = (jie[a])
                c = b.args[0]
                eq_final = []
                eq_final1 = []
                jie_final = {a[0]: c.args[0], a[1]: c.args[1]}
                if len(f1_symbol) == 3:
                    eq_final.append([f1.subs(jie_final), 0])
                    eq_final1.append([eqs[0][0], eqs[0][1]])
                if len(f2_symbol) == 3:
                    eq_final.append([f2.subs(jie_final), 0])
                    eq_final1.append([eqs[1][0], eqs[1][1]])
                if len(f3_symbol) == 3:
                    eq_final.append([f3.subs(jie_final), 0])
                    eq_final1.append([eq[0], eq[1]])

                self.steps.append(["", "将%s = %s，%s = %s代入%s,得"
                                   % (new_latex(a[0]), new_latex(c.args[0]), new_latex(a[1]), new_latex(c.args[1]),
                                      self.output_eq(eq_final1[0]))])
                self.steps.append(["", self.output_eq(eq_final[0])])
                self.output.append(BaseEq(eq_final[0]))
            else:
                stepsolver1 = JieFangChenZu().solver(args[0])
                self.steps += stepsolver1.steps
                stepsolver2 = DaiRuFangChenZu().solver(args[1], stepsolver1.output[0])
                self.steps += stepsolver2.steps
                self.output.append(stepsolver2.output[0])
        return self


# 根据一组解列二元一次方程
class ErYuanYiCi003(BaseFunction):
    def solver(self, *args):
        eqs = args[0].sympify()
        symbol = [eqs[0][0], eqs[1][0]]
        self.steps.append(["", "先围绕%s列一组算式" % (BaseEqs(eqs).printing())])
        if eqs[1][1] >= 0:
            self.steps.append(["", "如%s + %s = %s，%s - %s = %s" % (new_latex(eqs[0][1]), new_latex(eqs[1][1]), new_latex(eqs[0][1] + eqs[1][1]), new_latex(eqs[0][1]), new_latex(eqs[1][1]), new_latex(eqs[0][1] - eqs[1][1]))])
        else:
            self.steps.append(["", "如%s - %s = %s，%s + %s = %s" % (new_latex(eqs[0][1]), new_latex(-eqs[1][1]), new_latex(eqs[0][1] + eqs[1][1]), new_latex(eqs[0][1]), new_latex(-eqs[1][1]), new_latex(eqs[0][1] - eqs[1][1]))])
        self.steps.append(["", "然后用%s、%s代换，得" % (new_latex(symbol[0]), new_latex(symbol[1]))])
        self.steps.append(["", BaseEqs([[symbol[0] + symbol[1], eqs[0][1] + eqs[1][1]],
                                        [symbol[0] - symbol[1], eqs[0][1] - eqs[1][1]]]).printing()])
        self.steps.append(["", "答案不唯一"])
        return self


if __name__ == '__main__':
    pass
